import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as func

class Gloss(nn.Module):
    def __init__(self):
        super(Gloss,self).__init__()


    #输入point是个1*4矩阵，plane是个4*1矩阵
    #输入怎么会有point的信息呢，按理来说应该是个加权求和的结果
    def forward(self, d_part_2 , plane):
        # #距离分母
        # d_part_1 = torch.sqrt(torch.sum(torch.pow(plane,2),0))
        # #距离分子
        # d_part_2 = torch.abs(torch.matmul(point,plane))
        # #距离
        # d = torch.div(d_part_2,d_part_1)
        #TODO 有点问题，我之前写错了
        #d_part_1 = torch.sum(torch.pow(plane, 2), 1)
        d_part_1 = torch.pow(plane[0,0],2) + torch.pow(plane[0,1],2) + torch.pow(plane[0,2],2)
        # print('123')
        # print(d_part_1)
        # print('123')
        #d_part_2 = torch.pow(torch.matmul(point, plane),2)
        d_part_2 = torch.pow(d_part_2, 2)
        loss = torch.div(d_part_1,d_part_2)
        loss = torch.sum(loss,0) * -1
        return loss

class Eloss(nn.Module):
    def __init__(self):
        super(Eloss, self).__init__()
        #TODO 现在考虑一下怎么把loss写到最优
        #TODO 如果接着使用距离平方反比是肯定不行的，关键是平方，平方取消了符号
        #TODO 原先的loss函数收敛到的肯定是极值，如果是正常的贴合
        #TODO 如果不用平方，其实就是给在平面两侧的采样点带上了极性，平面本身是正性。loss增大的目的达到了，但是没解决梯度方向不正确的问题
        #TODO 单纯来看加个E为底数的想法，确实解决了点过近的时候会无限吸引的问题，但是也可能会导致梯度太小（考虑用常数项M增大之，理论上应该是增大的越多贴合的越好)

        #TODO 那么。。怎么解决远处点会吸引的问题呢
        #TODO 切入进去之后，梯度方向理应向外，这点是最难以想象的，咋办呢
        #TODO 切进任何一个点就能让这个点爆发出极大的loss，而且梯度向外，我们手上拿着的是符号距离


    def forward(self, fuck, plane):
        d_part_1 = torch.pow(plane[0, 0], 2) + torch.pow(plane[0, 1], 2) + torch.pow(plane[0, 2], 2)
        d_part_2 = torch.pow(fuck, 2)
        loss = torch.sum(torch.div(d_part_1,d_part_2),0) * -1